package com.white.camlib;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Binder;
import android.os.IBinder;
import android.util.Pair;
import android.view.TextureView;
import android.view.ViewGroup;

import com.white.loglib.L;

import java.util.concurrent.ExecutorService;

public class CameraService extends Service
{


    private Camera mCamera;
    private SurfaceTexture mSurfaceTexture;
    private AutoFitTextureView mTextureView;
    private PreviewHideWindow previewHideWindow;

    private int screenWidth, screenHeight;
    private final Object mLock = new byte[0];

    /**机器人默认后置摄像头*/
    private boolean isFrontCamera = false;

    @Override
    public void onCreate() {
        super.onCreate();
        Context context = getApplicationContext();
        int sw = context.getResources().getDisplayMetrics().widthPixels;
        int sh = context.getResources().getDisplayMetrics().heightPixels;
        screenWidth = Math.max(sw, sh);
        screenHeight = Math.min(sw, sh);
        L.e("camera service 获取到屏幕尺寸为：width = " + screenWidth + ", height = " + screenHeight +"，将作为默认预览尺寸");
        mBinder = new MyBinder();
        previewHideWindow = new PreviewHideWindow(getApplicationContext());
        //服务启动开启摄像头
        openCamera();
        if(mCamera == null){
            L.e("打开摄像头失败");
        }
    }

    public void openCamera(){
        if(mCamera != null) return;

        synchronized (mLock){
            try {
                mCamera = CameraKit.openCamera(isFrontCamera);
            }catch (Exception e){
                L.e("打开摄像头出现错误：" + e.getLocalizedMessage());
            }
        }
    }

    public void closeCamera(){
        if(mCamera == null) return;

        synchronized (mLock){
            try {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }catch (Exception e){
                L.e("打开摄像头出现错误：" + e.getLocalizedMessage());
            }
        }
    }

    private CameraKit.FrameCallback mFrameCallback;
    private CameraKit.TextureAttachCallback mTextureAttachCallback;

    private boolean noDisplayMode;

    private boolean fitParent;
    private int mTextureSpecificWidth, mTextureSpecificHeight;
    /**屏幕方向标识*/
    private int mScreenRotation;

    private boolean assertCamAvailable(){
        if(mCamera != null){
            try {
                mCamera.getParameters();
                return true;
            }catch (Exception e){
                mCamera.release();
                mCamera = null;
                return false;
            }
        }
        return false;
    }

    public void attach(ViewGroup parent, boolean fitParent,
                       int widSpecific, int heiSpecific,
                       int screenRotation,
                       CameraKit.FrameCallback frameCallback, CameraKit.TextureAttachCallback...attachCallbacks){
        if(!assertCamAvailable()){
            openCamera();
        }
        this.fitParent = fitParent;
        mTextureSpecificWidth = widSpecific;
        mTextureSpecificHeight = heiSpecific;

        mScreenRotation = screenRotation;

        //无窗口模式
        noDisplayMode = parent == null || parent.getContext() == null;
        //创建textureview
        if(mTextureView == null){
            mTextureView = new AutoFitTextureView(noDisplayMode ? getApplicationContext() : parent.getContext());
            //有的设备不需要镜像
            mTextureView.setScaleX(-1);
            mTextureView.setSurfaceTextureListener(listener);
        }else{
            CameraKit.unregisterFrameCallback(mCamera);
            CameraKit.stopPreview(mCamera);
        }
        mFrameCallback = frameCallback;
        if(attachCallbacks != null && attachCallbacks.length > 0){
            mTextureAttachCallback = attachCallbacks[0];
        }
        previewHideWindow.detach();
        removeViewParent();

        if(noDisplayMode){
            L.e("无显示模式");
            previewHideWindow.attach(mTextureView);
        }else{
            ViewGroup.MarginLayoutParams p = new ViewGroup.MarginLayoutParams(parent.getWidth(), parent.getHeight());
            if(fitParent){
                L.e("parent适应模式，parent wid = " +parent.getWidth() +", hei = " + parent.getHeight());
                mTextureView.setAspectRatio(parent.getWidth(), parent.getHeight());
            }else{
                L.e("指定大小模式，texture wid = " + mTextureSpecificWidth +", hei = " + mTextureSpecificHeight);
                mTextureView.setAspectRatio(mTextureSpecificWidth, mTextureSpecificHeight);
            }
            //在最底层添加textureview，避免覆盖上层展示view
            parent.addView(mTextureView, 0, p);
        }
    }

    private void removeViewParent(){
        if(mTextureView != null && mTextureView.getParent() != null){
            ViewGroup p = (ViewGroup) mTextureView.getParent();
            p.removeView(mTextureView);
        }
    }

    public void detach(){
        CameraKit.unregisterFrameCallback(mCamera);
        CameraKit.stopPreview(mCamera);
        previewHideWindow.detach();
        removeViewParent();
        mTextureAttachCallback = null;
        mFrameCallback = null;
    }

    public void takePicture(String path, CameraKit.PictureCallback callback, final ExecutorService...service){
        if(mCamera != null){
            CameraKit.takePhoto(mCamera, CameraKit.getCameraId(isFrontCamera),  mScreenRotation, path, callback, service);
        }
    }

    public void stopPreview(){
        if(mCamera != null){
            CameraKit.stopPreview(mCamera);
        }
    }

    public void startPreview(){
        if(mCamera != null && mSurfaceTexture != null){
            CameraKit.startTexurePreview(mCamera, mSurfaceTexture);
        }
    }

    private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            mSurfaceTexture = surface;
            if(noDisplayMode){
                //统一使用屏幕大小配置预览画面大小，因为识别需要用到帧数据，避免大小不同引起不必要的麻烦
                camConfig(screenWidth, screenHeight);
            }else if(fitParent){
                camConfig(width, height);
            }else{
                camConfig(mTextureSpecificWidth, mTextureSpecificHeight);
            }
            CameraKit.startTexurePreview(mCamera, mSurfaceTexture);
            if(mFrameCallback != null){
                CameraKit.registerFrameCallback(mCamera, currentPreviewSize.width, currentPreviewSize.height, ImageFormat.NV21, mFrameCallback);
            }
            if(mTextureAttachCallback != null){
                mTextureAttachCallback.onAvailable(surface,
                        currentPreviewSize.width, currentPreviewSize.height,
                        width, height);
            }
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            //不处理
//            CameraKit.setupBaseParams(width , height, mCamera);
//            CameraKit.adjustPreviewOrientation((Activity)(mTextureView.getContext()),
//                    CameraKit.getCameraId(false), mCamera);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
//            if(mCamera != null){
//                CameraKit.stopPreview(mCamera);
//            }
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {

        }
    };

    private Camera.Size currentPreviewSize;
    private void camConfig(int w, int h){
        if(mCamera != null){
            Pair<Camera.Size, Camera.Size> param = CameraKit.setupBaseParams(w, h, mCamera);
            CameraKit.adjustPreviewOrientation(mScreenRotation, CameraKit.getCameraId(isFrontCamera), mCamera);
            if(param != null){
                currentPreviewSize = param.first;
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private MyBinder mBinder;
    public class MyBinder extends Binder
    {

        public CameraService getService(){
            return CameraService.this;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mCamera != null){
            CameraKit.releaseCamera(mCamera);
        }
    }
}
